package com.free.framework.mvp;

import android.support.annotation.CallSuper;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;

import com.free.framework.business.BaseModel;
import com.free.framework.business.ResponseExceptionHandler;
import com.free.framework.business.ServerException;

import java.lang.ref.WeakReference;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import rx.subscriptions.CompositeSubscription;

/**
 * @author free
 * @date 16/10/24
 * @desc BaseMvpPresenter
 */
public class BaseMvpPresenter<V extends IMvpView> implements IMvpPresenter<V> {

    private WeakReference<V> mViewRef;

    private CompositeSubscription mSubscriptions = new CompositeSubscription();

    @UiThread
    @Override
    public void attachView(V view) {
        mViewRef = new WeakReference<>(view);
    }

    @UiThread
    @Nullable
    public V getView() {
        return mViewRef == null ? null : mViewRef.get();
    }

    @UiThread
    public boolean isViewAttached() {
        return mViewRef != null && mViewRef.get() != null;
    }

    @UiThread
    @Override
    public void detachView(boolean retainInstance) {
        if (mViewRef != null) {
            mViewRef.clear();
            mViewRef = null;
        }
    }


    @SuppressWarnings("unchecked")
    @Override
    public void subscribeNetwork(Observable observable, Subscriber subscriber) {
        mSubscriptions.add(observable.compose(this.transformer())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber));
    }

    @SuppressWarnings("unchecked")
    @Override
    public void subscribeNetwork(Observable observable, Subscriber subscriber, Observable.Transformer transformer) {
        mSubscriptions.add(observable.compose(transformer)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber));
    }



    @SuppressWarnings("unchecked")
    public <T> Observable.Transformer<BaseModel<T>, T> transformer() {

        return new Observable.Transformer<BaseModel<T>, T>() {
            @Override
            public Observable<T> call(Observable<BaseModel<T>> baseModelObservable) {
                return baseModelObservable.map(new Func1<BaseModel<T>, T>() {
                    @Override
                    public T call(BaseModel<T> tBaseModel) {
                        if (tBaseModel.code!=0) {
                            throw new ServerException(tBaseModel.code,tBaseModel.msg);
                        }
                        return tBaseModel.data;
                    }
                }).onErrorResumeNext(new Func1<Throwable, Observable<? extends T>>() {
                    @Override
                    public Observable<? extends T> call(Throwable throwable) {
                        if (throwable instanceof ServerException){
                            return Observable.error(throwable);
                        }else{
                            return Observable.error(ResponseExceptionHandler.handleResponseException(throwable));
                        }
                    }
                });
            }
        };
    }



    @Override
    public void resume() {
    }

    @Override
    public void pause() {
        if (mSubscriptions.isUnsubscribed()) {
            mSubscriptions.unsubscribe();
        }
    }

    @CallSuper
    @Override
    public void destroy() {
        detachView(false);
        if (mSubscriptions.isUnsubscribed()) {
            mSubscriptions.unsubscribe();
        }
    }

}
